package org.wheel.plugins.toolkit.jdbc.pool.util.excution;

import cn.hutool.core.lang.Pair;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import org.wheel.module.core.exception.NormalException;
import org.wheel.plugins.toolkit.jdbc.pool.bean.DatabaseConnection;
import org.wheel.plugins.toolkit.jdbc.pool.util.DynamicJdbcPoolUtil;

import java.util.Collection;
import java.util.List;
import java.util.Map;

@Slf4j
public class SqlTransactionExecutor {

    private final DynamicJdbcPoolUtil dynamicJdbcPool = DynamicJdbcPoolUtil.getInstance();

    public String namedParameterBatchInTransaction(DatabaseConnection conn,
                                     Collection<Pair<String, Map<String, Object>>> batchPairs){
        JdbcTemplate tpl = dynamicJdbcPool.getOrCreateJdbcTemplate(conn);
        NamedParameterJdbcTemplate npt = new NamedParameterJdbcTemplate(tpl);
        DataSourceTransactionManager txMgr = new DataSourceTransactionManager(tpl.getDataSource());
        TransactionTemplate txTpl = new TransactionTemplate(txMgr);
        return txTpl.execute(status -> {
            try {
                for (Pair<String, Map<String, Object>> p : batchPairs) {
                    npt.update(p.getKey(), p.getValue());
                }
                return null; // 成功
            } catch (Exception e) {
                log.error("批量事务执行失败", e);
                status.setRollbackOnly();
                return NormalException.getErrorInfoFromException(e);
            }
        });
    }

    /**
     * 不同 SQL + 不同参数 批量事务执行
     *
     * @return null=成功，否则=错误描述
     */
    public String batchInTransaction(DatabaseConnection conn,
                                     Collection<Pair<String, Object[]>> batchPairs) {
        JdbcTemplate tpl = dynamicJdbcPool.getOrCreateJdbcTemplate(conn);
        DataSourceTransactionManager txMgr = new DataSourceTransactionManager(tpl.getDataSource());
        TransactionTemplate txTpl = new TransactionTemplate(txMgr);
        return txTpl.execute(status -> {
            try {
                for (Pair<String, Object[]> p : batchPairs) {
                    tpl.update(p.getKey(), p.getValue());
                }
                return null; // 成功
            } catch (Exception e) {
                log.error("批量事务执行失败", e);
                status.setRollbackOnly();
                return NormalException.getErrorInfoFromException(e);
            }
        });
    }

    /**
     * 同一条 SQL 批量不同参数（JdbcTemplate.batchUpdate）
     */
    public int[] batchSameSql(DatabaseConnection conn, String sql, List<Object[]> batchArgs) {
        JdbcTemplate tpl = dynamicJdbcPool.getOrCreateJdbcTemplate(conn);
        return tpl.batchUpdate(sql, batchArgs);
    }

    public int[] namedParameterBatchSameSql(DatabaseConnection conn, String sql, List<Map<String, Object>> batchArgs) {
        JdbcTemplate tpl = dynamicJdbcPool.getOrCreateJdbcTemplate(conn);
        NamedParameterJdbcTemplate npt = new NamedParameterJdbcTemplate(tpl);
        return npt.batchUpdate(sql, batchArgs.toArray(new Map[0]));
    }
}